<script lang="ts" setup>
import { reactive, ref } from 'vue';

import { useVbenModal } from '@vben/common-ui';

import {
  Form,
  FormItem,
  Input,
  message,
  Radio,
  RadioGroup,
  Tree,
} from 'ant-design-vue';

import {
  getMenuPageApi,
  getRoleInfoApi,
  storeRoleApi,
  updateRoleApi,
} from '#/api';

const gridApi = ref();
const record = ref();
const formRef = ref();
const options = ref();
// 勾选的key
const checkedKeys = ref([]);
// 提交的勾选的key,会进行特殊处理，包含半勾状态的父节点halfCheckedKeys
const submitCheckedKeys = ref<any>([]);
// 所有叶子节点key
const leafKeys = ref<any>([]);

const labelCol = { span: 5 };
const wrapperCol = { span: 17 };

interface FormData {
  name: string;
  mark: string;
  status: number;
  roles: string[];
}

const formData = reactive<FormData>({
  name: '',
  mark: '',
  status: 1,
  rules: [],
});

const rules = {
  name: [{ required: true, message: '请输入角色名称', trigger: 'blur' }],
  mark: [{ required: true, message: '请输入角色标识', trigger: 'blur' }],
  // rules: [{ required: true, message: '请选择角色角色', trigger: 'blur' }],
};

const fieldNames: TreeProps['fieldNames'] = {
  title: 'name',
  key: 'id',
};

// 获取所有子节点
const getLeafNodeIds = (treeData: any) => {
  const leafNodeIds: any = [];

  function traverse(node: any) {
    // 如果当前节点没有 children 或 children 是空数组，则它是叶子节点
    if (!node.children || node.children.length === 0) {
      leafNodeIds.push(node.id);
    } else {
      // 否则，递归遍历每个子节点
      for (const child of node.children) {
        traverse(child);
      }
    }
  }

  // 遍历树的根节点
  for (const root of treeData) {
    traverse(root);
  }
  return leafNodeIds;
};

const [Modal, modalApi] = useVbenModal({
  // 重置表单
  onBeforeClose() {
    formRef.value.resetFields();
  },
  // 取消按钮
  onCancel() {
    modalApi.close();
  },
  // 确认提交
  onConfirm() {
    // 表单验证
    formRef.value.validate().then(() => {
      modalApi.setState({ loading: true, confirmLoading: true });
      const data = formData;
      data.rules = submitCheckedKeys;
      const id = record.value.id;
      const Api = id ? updateRoleApi(id, data) : storeRoleApi(data);
      Api.then(() => {
        message.success('操作成功');
        gridApi.value?.reload();
        modalApi.close();
      }).finally(() => {
        modalApi.setState({ loading: false, confirmLoading: false });
      });
    });
  },
  // 打开抽屉回调
  onOpenChange(isOpen: boolean) {
    record.value = isOpen ? modalApi.getData()?.record || {} : {};
    gridApi.value = isOpen ? modalApi.getData()?.gridApi : null;
    if (isOpen) {
      getMenuPageApi().then((data) => {
        options.value = data;
        leafKeys.value = getLeafNodeIds(data);
      });
      if (record.value.id && record.value) {
        getRoleInfoApi(record.value.id).then((data) => {
          // [0=>"1", 1=>"2"] 把数组字符串转为整数
          data.rules = data.rules.map(Number);
          // 只选中叶子节点
          checkedKeys.value = data.rules.filter((item: any) => {
            return leafKeys.value.includes(item);
          });
          submitCheckedKeys.value = data.rules;
          Object.assign(formData, data);
        });
      }
    }
  },
});

// 树形选中的时候把父级未选中的key合并
const onCheck = (mCheckedKeys, e) => {
  checkedKeys.value = mCheckedKeys;
  // 提交的时候需要将半选的父节点也提交上
  submitCheckedKeys.value = [...mCheckedKeys, ...e.halfCheckedKeys];
};
</script>
<template>
  <Modal class="w-[700px]">
    <Form
      ref="formRef"
      :label-col="labelCol"
      :model="formData"
      :rules="rules"
      :wrapper-col="wrapperCol"
    >
      <FormItem label="角色名称" name="name">
        <Input v-model:value="formData.name" />
      </FormItem>
      <FormItem label="角色标识" name="mark">
        <Input v-model:value="formData.mark" />
      </FormItem>
      <FormItem label="状态" name="status">
        <RadioGroup v-model:value="formData.status">
          <Radio :value="1">正常</Radio>
          <Radio :value="0">禁用</Radio>
        </RadioGroup>
      </FormItem>
      <FormItem label="菜单权限" name="rules">
        <Tree
          v-model:checked-keys="checkedKeys"
          :field-names="fieldNames"
          :tree-data="options"
          checkable
          @check="onCheck"
        />
      </FormItem>
    </Form>
  </Modal>
</template>
